/**
 *    Copyright (C) 2008,2009  Victor Smirnov <aist11@gmail.com>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License along
 *    with this program; if not, write to the Free Software Foundation, Inc.,
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *    See LICENSE.exceptions in the root folder of this project for possible
 *    exceptions
 *
 */

#ifndef _CUBEFS_CORE_BTREE_PAGES_NODE_BUILDER_INTRNL_HPP
#define	_CUBEFS_CORE_BTREE_PAGES_NODE_BUILDER_INTRNL_HPP

#include <cubefs/core/tools/types/typelist.hpp>

namespace cubefs    {
namespace btree     {
    
using namespace cubefs::tools;

template <
        typename Profile,
        typename Name,
        template <typename, typename, typename, typename, Int, bool, typename, typename, typename> class NodeTypeFactory,
        Int      Indexes,
        typename Lists,
        typename Key,
        bool     PackedMapType,
        typename LeafValue,
        typename InternalValue,
        typename ResultList,
        Int Level,
        bool All
>
class AddTypesQuadToList;




template <
        typename Profile,
        typename Name,
        template <typename, typename, typename, typename, Int, bool, typename, typename, typename> class NodeTypeFactory,
        Int      Indexes,
        typename Lists,
        typename Key,
        bool     PackedMapType,
        typename LeafValue,
        typename InternalValue,
        typename ResultList
>
class AddTypesQuadToList <
        Profile,
        Name,
        NodeTypeFactory,
        Indexes,
        Lists,
        Key,
        PackedMapType,
        LeafValue,
        InternalValue,
        ResultList,
        ANY_LEVEL,
        true
> {
    static const BigInt Level = ANY_LEVEL;

    typedef typename NodeTypeFactory<
            Profile,
            Name,
            Key,
            LeafValue,
            Indexes,
            PackedMapType,
            typename Lists::LeafPagePartsList,
            typename Lists::BasePagePartsList,
            NodeDescriptor<false, true, Level>
    >::Type                                                                     LeafType;

    typedef typename NodeTypeFactory<
            Profile,
            Name,
            Key,
            LeafValue,
            Indexes,
            PackedMapType,
            typename AppendTool<
                typename Lists::RootPagePartsList,
                typename Lists::LeafPagePartsList
            >::Result,
            typename Lists::BasePagePartsList,
            NodeDescriptor<true, true, Level>
    >::Type                                                                     RootLeafType;


    typedef typename NodeTypeFactory<
            Profile,
            Name,
            Key,
            InternalValue,
            Indexes,
            PackedMapType,
            typename AppendTool<
                typename Lists::RootPagePartsList,
                typename Lists::InternalPagePartsList
            >::Result,
            typename Lists::BasePagePartsList,
            NodeDescriptor<true, false, Level>
    >::Type                                                                     RootType;


    typedef typename NodeTypeFactory<
            Profile,
            Name,
            Key,
            InternalValue,
            Indexes,
            PackedMapType,
            typename Lists::InternalPagePartsList,
            typename Lists::BasePagePartsList,
            NodeDescriptor<false, false, Level>
    >::Type                                                                     InternalType;

public:
    typedef typename AppendTool<
                        typename TypeListTool<
                            LeafType,
                            RootLeafType,
                            RootType,
                            InternalType
                        >::List,
                        ResultList
    >::Result                                                                   List;
};


template <
        typename Profile,
        typename Name,
        template <typename, typename, typename, typename, Int, bool, typename, typename, typename> class NodeTypeFactory,
        Int      Indexes,
        typename Lists,
        typename Key,
        bool     PackedMapType,
        typename LeafValue,
        typename InternalValue,
        typename ResultList,
        bool     All
>
class AddTypesQuadToList<
        Profile,
        Name,
        NodeTypeFactory,
        Indexes,
        Lists,
        Key,
        PackedMapType,
        LeafValue,
        InternalValue,
        ResultList,
        0,
        All
> {
    static const Int Level = 0;

    typedef typename NodeTypeFactory<
            Profile,
            Name,
            Key,
            LeafValue,
            Indexes,
            PackedMapType,
            typename Lists::LeafPagePartsList,
            typename Lists::BasePagePartsList,
            NodeDescriptor<false, true, Level>
    >::Type                                                                     LeafType;

    typedef typename NodeTypeFactory<
            Profile,
            Name,
            Key,
            LeafValue,
            Indexes,
            PackedMapType,
            typename AppendTool<
                typename Lists::RootPagePartsList,
                typename Lists::LeafPagePartsList
            >::List,
            typename Lists::BasePagePartsList,
            NodeDescriptor<true, true, Level>
    >::Type                                                                     RootLeafType;

public:
    typedef typename AppendTool<
                        typename TypeListTool<
                            LeafType,
                            RootLeafType
                        >::List,
                        ResultList
    >::Result                                                                   List;
};

template <
        typename Profile,
        typename Name,
        template <typename, typename, typename, typename, Int, bool, typename, typename, typename> class NodeTypeFactory,
        Int      Indexes,
        typename Lists,
        typename Key,
        bool     PackedMapType,
        typename LeafValue,
        typename InternalValue,
        typename ResultList,
        Int Level,
        bool All
>
class AddTypesQuadToList {

    typedef typename NodeTypeFactory<
            Profile,
            Name,
            Key,
            LeafValue,
            Indexes,
            PackedMapType,
            typename AppendTool<
                typename Lists::RootPagePartsList,
                typename Lists::InternalPagePartsList
            >::Result,
            typename Lists::BasePagePartsList,
            NodeDescriptor<true, false, Level>
    >::Type                                                                     RootType;


    typedef typename NodeTypeFactory<
            Profile,
            Name,
            Key,
            InternalValue,
            Indexes,
            PackedMapType,
            typename Lists::InternalPagePartsList,
            typename Lists::BasePagePartsList,
            NodeDescriptor<false, false, Level>
    >::Type                                                                     InternalType;

public:
    typedef typename AppendTool<
                        typename TypeListTool<
                            RootType,
                            InternalType
                        >::List,
                        ResultList
    >::Result                                                                   List;
};








template <
        typename Profile,
        typename Name,
        template <typename, typename, typename, typename, Int, bool, typename, typename, typename> class NodeTypeFactory,
        Int      Indexes,
        typename Lists,
        typename KeysList,
        bool     PackedMapType,
        typename LeafValue,
        typename InternalValue,
        typename ResultList = NullType,
        Int Level = 0
>
class NodeTypeListBuilderTool;


template <
        typename Profile,
        typename Name,
        template <typename, typename, typename, typename, Int, bool, typename, typename, typename> class NodeTypeFactory,
        Int      Indexes,
        typename Lists,
        typename Head,
        typename Tail,
        bool     PackedMapType,
        typename LeafValue,
        typename InternalValue,
        typename ResultList,
        Int Level
>
class NodeTypeListBuilderTool<
        Profile,
        Name,
        NodeTypeFactory,
        Indexes,
        Lists,
        TypeList<Head, Tail>,
        PackedMapType,
        LeafValue,
        InternalValue,
        ResultList,
        Level
> {
    typedef Head                                                                Key;
    
    typedef typename AddTypesQuadToList<
                        Profile,
                        Name,
                        NodeTypeFactory,
                        Indexes,
                        Lists,
                        Key,
                        PackedMapType,
                        LeafValue,
                        InternalValue,
                        ResultList,
                        Level,
                        false
    >::List                                                                     List;

public:

    typedef typename NodeTypeListBuilderTool<
                        Profile,
                        Name,
                        NodeTypeFactory,
                        Indexes,
                        Lists,
                        Tail,
                        PackedMapType,
                        LeafValue,
                        InternalValue,
                        List,
                        Level + 1
    >::NodeTypesList                                                            NodeTypesList;
};


template <
        typename Profile,
        typename Name,
        template <typename, typename, typename, typename, Int, bool, typename, typename, typename> class NodeTypeFactory,
        Int      Indexes,
        typename Lists,
        typename Head,
        bool     PackedMapType,
        typename LeafValue,
        typename InternalValue,
        typename ResultList,
        Int Level
>
class NodeTypeListBuilderTool<
        Profile,
        Name,
        NodeTypeFactory,
        Indexes,
        Lists,
        TypeList<Head, NullType>,
        PackedMapType,
        LeafValue,
        InternalValue,
        ResultList,
        Level
> {
    typedef Head                                                                Key;

    typedef typename AddTypesQuadToList<
                        Profile,
                        Name,
                        NodeTypeFactory,
                        Indexes,
                        Lists,
                        Key,
                        PackedMapType,
                        LeafValue,
                        InternalValue,
                        ResultList,
                        ANY_LEVEL,
                        false
    >::List                                                                     List;

public:

    typedef List                                                                NodeTypesList;
};

}
}

#endif // _CUBEFS_CORE_BTREE_PAGES_NODE_BUILDER_INTRNL_HPP

